package com.sun.filesigndemo.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.sun.filesigndemo.bussiness.mapper.FileMapper;
import com.sun.filesigndemo.common.conf.Global;
import com.sun.filesigndemo.common.statusCode.ResultMsg;
import com.sun.filesigndemo.common.utils.FileUtils;
import com.sun.filesigndemo.common.utils.UploadUtil;
import org.omg.PortableInterceptor.SYSTEM_EXCEPTION;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;


import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.util.*;

@Controller
@RequestMapping("public")
public class BaseController {

    //上传文件路径
    private String configUpLoadPath = Global.get("app.upLoadPath").replaceAll("~",System.getProperty("user.home"));

    @Autowired
    private FileMapper fileMapper;

    //行号
    private int lineNumber = 0;



    @RequestMapping(value = "basic", method = RequestMethod.GET)
    @ResponseBody
    public Map<String, Object> getAllIntentAndSlot(HttpServletRequest request,String jsonPath) throws IOException {

        File file = new File(jsonPath);

        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
        StringBuffer message = new StringBuffer();
        String line = null;
        while ((line = bufferedReader.readLine()) != null) {
            message.append(line);
        }
        String defaultString = message.toString();
        String result = defaultString.replace("\r\n", "").replaceAll(" +", "");
        //System.out.println(result);

        JSONObject jsonObject = JSON.parseObject(result);
        //遍历json对象 拼想要的结果
        ArrayList<HashMap> arrayList = new ArrayList<>();
        for(Map.Entry<String,Object> entry: jsonObject.entrySet()){
            HashMap map = new HashMap();
            map.put("intent",entry.getKey());
            JSONObject sub = (JSONObject) JSON.toJSON(entry.getValue());
            if(sub.get("slots") != null){
                map.put("slots",sub.get("slots"));
            }
            arrayList.add(map);
        }
        int m = 1;

        return ResultMsg.successData(arrayList);
    }

    @RequestMapping(value = "allRow",method = RequestMethod.GET)
    @ResponseBody
    public Map<String,Object> getAllRow(HttpServletRequest request,String txtPath) throws IOException {

        File file = new File(txtPath);

        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
        ArrayList<String> list = new ArrayList<String>();
        String line = null;
        while((line = bufferedReader.readLine())!=null){
            list.add(line);
        }
        return ResultMsg.successData((list));
    }

    @RequestMapping(value = "preRow", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, Object> getPreRow(HttpServletRequest request,int rowNum,String stylePath,String txtPath) throws IOException {
        LineNumberReader reader = new LineNumberReader(new FileReader(new File(stylePath)));



        String s = reader.readLine();

        while(s!=null){
            int m = reader.getLineNumber();
            if(m == rowNum){
                fileMapper.updateStatusAndLastRowByPath(txtPath,rowNum);
                return ResultMsg.successData(s);
            }
            s=reader.readLine();
        }

        return null;
    }

    @RequestMapping(value = "nextRow", method = RequestMethod.GET)
    @ResponseBody
    public Map<String,Object> getNextRow(HttpServletRequest request,int rowNum,String postTxt,String postSlot,String selectedIntent,String txtPath,String isStartWrite,String style) throws IOException {



        File temFile = new File(txtPath);


        String pp = Global.get("fileOut.outPutPath").replaceAll("~",System.getProperty("user.home"));



        File targetFile = new File(pp+temFile.getName()+"_intent_slot.txt");


        File target2File = new File(pp+temFile.getName()+"_intent.txt");



        File styleFile = new File(configUpLoadPath+"style"+File.separator+temFile.getName()+"style.txt");

        //先修改上一行的内容
        LineNumberReader reader = new LineNumberReader(new FileReader(new File(txtPath)));


        FileOutputStream fileOutputStream;
        FileOutputStream fileOutputStream2;

        //先拿出文件上一次标记过的行号
        HashMap temmap = (HashMap) fileMapper.selectLastRowStatusByFilePath(txtPath);

        //rowNum = (int) temmap.get("lastSignRow")+1;

        if(temmap.get("status").toString().equals("false")){
            //未被标记过得文件 从头开始写输出
            fileOutputStream = new FileOutputStream(targetFile, false);
            fileOutputStream2 = new FileOutputStream(target2File,false);
        }else {
            //标记过得从屁股后面跟上
            fileOutputStream = new FileOutputStream(targetFile, true);
            fileOutputStream2 = new FileOutputStream(target2File,true);
        }



        //样式写入流
        FileOutputStream styleOutPutStream;




        //同输出文件道理一样
        if(temmap.get("status").toString().equals("false")){
            styleOutPutStream = new FileOutputStream(styleFile, false);
        }else {
            styleOutPutStream = new FileOutputStream(styleFile, true);
        }

        //reader.mark((int) (textResource.getFile().length() + 1));
        int lastRow = (int) temmap.get("lastSignRow");


        String[] arrayTxt = postTxt.split(",");
        String[] arraySlot = postSlot.split(",");

        //FileReader in = new FileReader(textResource.getFile());
        String lastStr = null;
        //该行是否已经修改过
        boolean hasChange = false;
        //换行符
        String newLine = System.getProperty("line.separator");
        //找index的时候截取用的str
        String str = null;
        String s = reader.readLine();
        lineNumber = rowNum;


        //防止字符有重复的时候用
        int temIndex = 0;

        if(selectedIntent == null) {
            selectedIntent = "UNKNOWNINTENT";
        }
        String originalTxt = "";

        while (s != null) {
            int m = reader.getLineNumber();
            //先修改上一行的内容
            if (lastRow == m && hasChange == false) {

                reader.mark(m);

//                String t = reader.readLine();
//
//                while (t != null){
//
//                }


                originalTxt = s;
                lastStr = selectedIntent + "\t\t" + s;


                StringBuilder stringBuilder2 = new StringBuilder(lastStr);
                stringBuilder2.insert(0,"lable_");


                //"\t\t".length()
                StringBuilder stringBuilder = new StringBuilder(lastStr);
                //字符串前先加上intent和TAB
                //stringBuilder.insert(0,selectedIntent );
                //每一个字符后面需要先加上|<unk>
                for (int i = selectedIntent.length() + "\t\t".length(), j = i; i < lastStr.length(); i++) {
                    stringBuilder.insert(j + 1, "|<unk>");
                    j = j + "|<unk>".length() + 1;
                }

                int index = 0;


                for (int i = 0; i < arrayTxt.length; i++) {
                    boolean isright = false;
                    boolean isNextRight = false;

                    //如果是单字符 不需要判断后续字符 只用确保字符后面是 <unk>l 就行了 直接插入
                    if (arrayTxt[i].length() == 1 && arrayTxt[i] != "") {
                        for (int j = 0; j < stringBuilder.length(); j++) {
                            String temp = String.valueOf(stringBuilder.charAt(j));
                            //相等 而且是没有插过的字符后面 才能插入
                            if (temp.equals(arrayTxt[i]) && String.valueOf(stringBuilder.charAt(j + 1)).equals("|") && String.valueOf(stringBuilder.charAt(j + 2)).equals("<") && String.valueOf(stringBuilder.charAt(j + 3)).equals("u") &&
                                    String.valueOf(stringBuilder.charAt(j + 4)).equals("n") && String.valueOf(stringBuilder.charAt(j + 5)).equals("k") && String.valueOf(stringBuilder.charAt(j + 6)).equals(">")) {
                                stringBuilder.replace(j + 1, j + 7, arraySlot[i]);

                                //插入完毕以后 跳出本次循环
                                break;
                            }
                        }
                    } else if (arrayTxt[i].length() > 1) {
                        //如果是多字符 首先判斷所有位相等 而且第一位字符 后面没有插入过 才能插入
                        char[] temaArrayTxTI = arrayTxt[i].toCharArray();
                        boolean isRight = false;
                        //记录所有需要插入位置的数组
                        LinkedList<Integer> insertIndex = new LinkedList<Integer>();
                        for (int j = 0; j < stringBuilder.length(); j++) {
                            for (int n = 0; n < temaArrayTxTI.length; n++) {
                                //挨个开始检查后续的每一个字符是否相等且没有插入过(不用再跟单字符一样判断一长串了 只要是查过了 j+m*7的位置 肯定不是原来的字符了
                                if (temaArrayTxTI[n] == stringBuilder.charAt(j + (n * 7))) {
                                    insertIndex.add(j + (n * 7));
                                } else {
                                    continue;
                                }
                            }
                            if (insertIndex.size() == temaArrayTxTI.length) {
                                isRight = true;
                                temIndex = insertIndex.get(0);
                                break;
                            } else {
                                insertIndex.clear();
                            }
                        }


                        if (isRight == true) {
                            //先插一个
                            for (int p = 0; p < temaArrayTxTI.length; p++) {
                                stringBuilder.replace(temIndex + 1, temIndex + 7, arraySlot[i]);
                                temIndex = temIndex + arraySlot[i].length() +1 ;
                            }
                        }
                    }

                }
                //写入文件
                //再加两个TAB再加上原文本
                stringBuilder = stringBuilder.append("\t\t"+originalTxt);

                style = style + "\t" + selectedIntent + "\t" + postTxt + "\t" + postSlot + '\t' + s;
                if(rowNum > getTotalLines(targetFile)+1){
                    fileOutputStream.write(stringBuilder.toString().getBytes());
                    fileOutputStream.write(newLine.getBytes());

                    fileOutputStream2.write(stringBuilder2.toString().getBytes());
                    fileOutputStream2.write(newLine.getBytes());

                    styleOutPutStream.write(style.getBytes());
                    styleOutPutStream.write(newLine.getBytes());
                }else {
                    FileUtils.replaceFileRandomRow(targetFile.getPath(),lastRow,stringBuilder.toString());
                    FileUtils.replaceFileRandomRow(target2File.getPath(),lastRow,stringBuilder2.toString());
                    FileUtils.replaceFileRandomRow(styleFile.getPath(),lastRow,style);
                }

                //在写入文件以后需要跟新文件的last_sign_row和status(status只要写了就改 省得还要分各种情况区分 麻烦)
                fileMapper.updateStatusAndLastRowByPath(txtPath,lastRow+1);


                //把样式写入文件进行保存
//                styleOutPutStream.write(style.getBytes());
//                styleOutPutStream.write(newLine.getBytes());

//                    int x = 1;
//                    reader.reset();
                hasChange = true;
            }


            if ((rowNum) == m) {

//                //先修改上次文件标注的行号
//                if(temmap.get("status").toString().equals("false")){
//                    fileMapper.updateStatusAndLastRowByPath(txtPath,la);
//                }
                //fileMapper.setLastRowByFilePath(txtPath,rowNum);

                HashMap map = new HashMap();
                map.put("str", s);
                map.put("lineNum", m);
                map.put("stylePath",styleFile.getPath());
                //把文件上次标注到哪一行也放进去
                map.put("rowNum",rowNum);

                //读取样式文件的相应行
                LineNumberReader styleReader = new LineNumberReader(new FileReader(styleFile));

                String styleLine = "";
                while((styleLine = styleReader.readLine())!=null){
                    if(rowNum == styleReader.getLineNumber()){
                        map.put("style",styleLine);
                    }else {
                        map.put("style","");
                    }
                }
                reader.close();
                return ResultMsg.successData(map);
            }
            s = reader.readLine();

        }
        reader.close();

        return ResultMsg.successData(s);
    }

    @RequestMapping(value = "showRow", method = RequestMethod.POST)
    @ResponseBody
    public Map<String,Object> showRow(HttpServletRequest request,int rowNum,String postTxt,String postSlot,String selectedIntent,String txtPath,String isStartWrite,String style) throws IOException {
        File temFile = new File(txtPath);


//

        String pp = Global.get("app.upLoadPath").replaceAll("~",System.getProperty("user.home"));

        File styleFile = new File(configUpLoadPath+"style"+File.separator+temFile.getName()+"style.txt");

        //先修改上一行的内容
        LineNumberReader reader = new LineNumberReader(new FileReader(new File(txtPath)));



        FileOutputStream fileOutputStream;

        //先拿出文件上一次标记过的行号
        HashMap temmap = (HashMap) fileMapper.selectLastRowStatusByFilePath(txtPath);

        //rowNum = (int) temmap.get("lastSignRow");


        rowNum = getTotalLines(styleFile)+1;
        fileMapper.updateLastRowByPath(txtPath,rowNum);


        String s = reader.readLine();

        while (s!=null){
            int m = reader.getLineNumber();
            if (rowNum == m) {
                //fileMapper.setLastRowByFilePath(txtPath,rowNum);

                HashMap map = new HashMap();
                map.put("str", s);
                map.put("lineNum", m);
                map.put("stylePath",styleFile.getPath());
                //把文件上次标注到哪一行也放进去
                map.put("rowNum",rowNum);

                //读取样式文件的相应行
                LineNumberReader styleReader = new LineNumberReader(new FileReader(styleFile));

                String styleLine = "";
                while((styleLine = styleReader.readLine())!=null){
                    if(rowNum == styleReader.getLineNumber()){
                        map.put("style",styleLine);
                    }else {
                        map.put("style","");
                    }
                }

                return ResultMsg.successData(map);
            }
            s = reader.readLine();
        }

        reader.close();

        return ResultMsg.successData(s);

    }


    static int getTotalLines(File file) throws IOException {
        LineNumberReader reader = new LineNumberReader(new FileReader(file));
        int lines = 0;
        String s = "a";
        while((s = reader.readLine())!=null){
            lines ++;
            //s = reader.readLine();
        }
        reader.close();
        return lines;
    }
}
